﻿//-----------------------------------------------------------------------
// <copyright file="Glow.cs" company="Noboru Project">
//      Copyright (c) Noboru Project. All rights reserved.
//
//      This source code is subject to terms and conditions of the New BSD License (BSD).
//      A copy of the license can be found in the License.html file at the root of this 
//      distribution. If you can not locate the New BSD License (BSD), please send an 
//      email to noboru_adm@live.com.
//      By using this source code in any fashion, you are agreeing to be bound by
//      the terms of the New BSD License (BSD) for Noboru.
//
//      You must not remove this notice, or any other, from this software.
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Noboru.Windows.Controls
{
    /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.Class"]/*' />
    [TemplatePart(Name = "BackgroundPart", Type = typeof(Canvas))]
    [TemplatePart(Name = "LayoutPart", Type = typeof(Grid))]
    [TemplatePart(Name = "RectangleTopLeftPart", Type = typeof(Rectangle))]
    [TemplatePart(Name = "RectangleTopPart", Type = typeof(Rectangle))]
    [TemplatePart(Name = "RectangleTopRightPart", Type = typeof(Rectangle))]
    [TemplatePart(Name = "RectangleMiddleRightPart", Type = typeof(Rectangle))]
    [TemplatePart(Name = "RectangleBottomRightPart", Type = typeof(Rectangle))]
    [TemplatePart(Name = "RectangleBottomPart", Type = typeof(Rectangle))]
    [TemplatePart(Name = "RectangleBottomLeftPart", Type = typeof(Rectangle))]
    [TemplatePart(Name = "RectangleMiddleLeftPart", Type = typeof(Rectangle))]
    [TemplatePart(Name = "RectangleMiddlePart", Type = typeof(Rectangle))]
    public class Glow : ContentControl
    {
        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.CornerRadiusProperty"]/*' />
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(System.Windows.CornerRadius), typeof(Glow), new PropertyMetadata(new System.Windows.CornerRadius(0), Glow.PropertyChangedCallback));

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.GlowDirectionProperty"]/*' />
        public static readonly DependencyProperty GlowDirectionProperty = DependencyProperty.Register("GlowDirection", typeof(GlowDirection), typeof(Glow), new PropertyMetadata(GlowDirection.Outer, Glow.PropertyChangedCallback));

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.GlowColorProperty"]/*' />
        public static readonly DependencyProperty GlowColorProperty = DependencyProperty.Register("GlowColor", typeof(Color), typeof(Glow), new PropertyMetadata(Colors.Transparent, Glow.PropertyChangedCallback));

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.GlowOpacityProperty"]/*' />
        public static readonly DependencyProperty GlowOpacityProperty = DependencyProperty.Register("GlowOpacity", typeof(double), typeof(Glow), new PropertyMetadata(1.0, Glow.PropertyChangedCallback));

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.GlowWidthProperty"]/*' />
        public static readonly DependencyProperty GlowWidthProperty = DependencyProperty.Register("GlowWidth", typeof(double), typeof(Glow), new PropertyMetadata(0.0, Glow.PropertyChangedCallback));

        private Canvas _backgroundPart;
        private CornerRadius _adjustedCornerRadius;
        private double _gradientBaseWidth;
        private double _gradientBaseHeight;
        private double _adjustedGradientWidth;
        private Grid _layoutPart;
        private Rectangle _rectangleTopLeftPart;
        private Rectangle _rectangleTopPart;
        private Rectangle _rectangleTopRightPart;
        private Rectangle _rectangleMiddleRightPart;
        private Rectangle _rectangleBottomRightPart;
        private Rectangle _rectangleBottomPart;
        private Rectangle _rectangleBottomLeftPart;
        private Rectangle _rectangleMiddleLeftPart;
        private Rectangle _rectangleMiddlePart;

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.Constructor"]/*' />
        public Glow()
        {
            this.DefaultStyleKey = typeof(Glow);
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.CornerRadius"]/*' />
        public CornerRadius CornerRadius
        {
            get
            {
                return (System.Windows.CornerRadius)this.GetValue(CornerRadiusProperty);
            }

            set
            {
                this.SetValue(CornerRadiusProperty, value);
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.GlowDirection"]/*' />
        public GlowDirection GlowDirection
        {
            get
            {
                return (GlowDirection)this.GetValue(GlowDirectionProperty);
            }

            set
            {
                this.SetValue(GlowDirectionProperty, value);
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.GlowColor"]/*' />
        public Color GlowColor
        {
            get
            {
                return (Color)this.GetValue(GlowColorProperty);
            }

            set
            {
                this.SetValue(GlowColorProperty, value);
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.GlowOpactiy"]/*' />
        public double GlowOpactiy
        {
            get
            {
                return (double)this.GetValue(GlowOpacityProperty);
            }

            set
            {
                this.SetValue(GlowOpacityProperty, value);
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.GlowWidth"]/*' />
        public double GlowWidth
        {
            get
            {
                return (double)this.GetValue(GlowWidthProperty);
            }

            set
            {
                this.SetValue(GlowWidthProperty, value);
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.BackgroundPart"]/*' />
        protected Canvas BackgroundPart
        {
            get
            {
                return this._backgroundPart;
            }

            set
            {
                this._backgroundPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.LayoutPart"]/*' />
        protected Grid LayoutPart
        {
            get 
            { 
                return this._layoutPart;
            }

            set 
            { 
                this._layoutPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleTopLeftPart"]/*' />
        protected Rectangle RectangleTopLeftPart
        {
            get 
            { 
                return this._rectangleTopLeftPart;
            }

            set 
            { 
                this._rectangleTopLeftPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleTopPart"]/*' />
        protected Rectangle RectangleTopPart
        {
            get 
            { 
                return this._rectangleTopPart;
            }

            set 
            { 
                this._rectangleTopPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleTopRightPart"]/*' />
        protected Rectangle RectangleTopRightPart
        {
            get
            {
                return this._rectangleTopRightPart;
            }

            set
            {
                this._rectangleTopRightPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleMiddleRightPart"]/*' />
        protected Rectangle RectangleMiddleRightPart
        {
            get
            {
                return this._rectangleMiddleRightPart;
            }

            set
            {
                this._rectangleMiddleRightPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleBottomRightPart"]/*' />
        protected Rectangle RectangleBottomRightPart
        {
            get
            {
                return this._rectangleBottomRightPart;
            }

            set
            {
                this._rectangleBottomRightPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleBottomPart"]/*' />
        protected Rectangle RectangleBottomPart
        {
            get
            {
                return this._rectangleBottomPart;
            }

            set
            {
                this._rectangleBottomPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleBottomLeftPart"]/*' />
        protected Rectangle RectangleBottomLeftPart
        {
            get
            {
                return this._rectangleBottomLeftPart;
            }

            set
            {
                this._rectangleBottomLeftPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleMiddleLeftPart"]/*' />
        protected Rectangle RectangleMiddleLeftPart
        {
            get
            {
                return this._rectangleMiddleLeftPart;
            }

            set
            {
                this._rectangleMiddleLeftPart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.RectangleMiddlePart"]/*' />
        protected Rectangle RectangleMiddlePart
        {
            get
            {
                return this._rectangleMiddlePart;
            }

            set
            {
                this._rectangleMiddlePart = value;
            }
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.OnApplyTemplate"]/*' />
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.BackgroundPart = (Canvas)GetTemplateChild("BackgroundPart");
            this.LayoutPart = (Grid)GetTemplateChild("LayoutPart");
            this.RectangleTopLeftPart = (Rectangle)GetTemplateChild("RectangleTopLeftPart");
            this.RectangleTopPart = (Rectangle)GetTemplateChild("RectangleTopPart");
            this.RectangleTopRightPart = (Rectangle)GetTemplateChild("RectangleTopRightPart");
            this.RectangleMiddleRightPart = (Rectangle)GetTemplateChild("RectangleMiddleRightPart");
            this.RectangleBottomRightPart = (Rectangle)GetTemplateChild("RectangleBottomRightPart");
            this.RectangleBottomPart = (Rectangle)GetTemplateChild("RectangleBottomPart");
            this.RectangleBottomLeftPart = (Rectangle)GetTemplateChild("RectangleBottomLeftPart");
            this.RectangleMiddleLeftPart = (Rectangle)GetTemplateChild("RectangleMiddleLeftPart");
            this.RectangleMiddlePart = (Rectangle)GetTemplateChild("RectangleMiddlePart");
        }

        /// <include file='Documentation\GlowDocumentation.uex' path='Members/Member[@for="Glow.OnContentChanged"]/*' />
        protected override void OnContentChanged(object oldContent, object newContent)
        {
            base.OnContentChanged(oldContent, newContent);

            if (oldContent != null)
            {
                ((FrameworkElement)oldContent).SizeChanged -= new SizeChangedEventHandler(this.Glow_SizeChanged);
            }

            FrameworkElement content = newContent as FrameworkElement;
            if (content != null)
            {
                content.SizeChanged += new SizeChangedEventHandler(this.Glow_SizeChanged);

                if (this.Content is Border)
                {
                    CornerRadius cornerRadius = (CornerRadius)content.GetValue(Border.CornerRadiusProperty);
                    this.CornerRadius = cornerRadius;
                }

                this.Visibility = content.Visibility;
            }

            this.LayoutGradient();
        }

        private static void PropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((Glow)sender).OnPropertyChanged(e);
        }

        private void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            this.LayoutGradient();
        }

        private void Glow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (this.Content != null)
            {
                FrameworkElement content = (FrameworkElement)this.Content;
                this._gradientBaseHeight = content.ActualHeight;
                this._gradientBaseWidth = content.ActualWidth;

                this.Visibility = content.Visibility;
            }
            else
            {
                this._gradientBaseHeight = this.Height;
                this._gradientBaseWidth = this.Width;
            }

            this.LayoutGradient();
        }

        private void LayoutGradient()
        {
            if (this._layoutPart != null)
            {
                double gradientWidth = Math.Round(this.GlowWidth);
                this._adjustedGradientWidth = Math.Round(this.GlowWidth);

                double roundAmount = Math.Round(this.CornerRadius.TopLeft);

                if (roundAmount > this._gradientBaseHeight / 2.0)
                {
                    roundAmount = Math.Round(this._gradientBaseHeight / 2.0);
                }

                if (roundAmount > this._gradientBaseWidth / 2.0)
                {
                    roundAmount = Math.Round(this._gradientBaseWidth / 2.0);
                }

                this._adjustedCornerRadius.TopLeft = roundAmount;

                roundAmount = Math.Round(this.CornerRadius.TopRight);

                if (roundAmount > this._gradientBaseHeight / 2.0)
                {
                    roundAmount = Math.Round(this._gradientBaseHeight / 2.0);
                }

                if (roundAmount > this._gradientBaseWidth / 2.0)
                {
                    roundAmount = Math.Round(this._gradientBaseWidth / 2.0);
                }

                this._adjustedCornerRadius.TopRight = roundAmount;

                roundAmount = Math.Round(this.CornerRadius.BottomRight);

                if (roundAmount > this._gradientBaseHeight / 2.0)
                {
                    roundAmount = Math.Round(this._gradientBaseHeight / 2.0);
                }

                if (roundAmount > this._gradientBaseWidth / 2.0)
                {
                    roundAmount = Math.Round(this._gradientBaseWidth / 2.0);
                }

                this._adjustedCornerRadius.BottomRight = roundAmount;

                roundAmount = Math.Round(this.CornerRadius.BottomLeft);

                if (roundAmount > this._gradientBaseHeight / 2.0)
                {
                    roundAmount = Math.Round(this._gradientBaseHeight / 2.0);
                }

                if (roundAmount > this._gradientBaseWidth / 2.0)
                {
                    roundAmount = Math.Round(this._gradientBaseWidth / 2.0);
                }

                this._adjustedCornerRadius.BottomLeft = roundAmount;

                roundAmount = Math.Round(this.CornerRadius.TopLeft); // temp

                FrameworkElement content = (FrameworkElement)this.Content;
                if (content != null)
                {
                    if (this.GlowDirection == GlowDirection.Inner)
                    {
                        this._layoutPart.SetValue(Canvas.ZIndexProperty, (int)content.GetValue(Canvas.ZIndexProperty) + 1);
                    }
                    else
                    {
                        this._layoutPart.SetValue(Canvas.ZIndexProperty, (int)content.GetValue(Canvas.ZIndexProperty) - 1);
                        this._layoutPart.Clip = null;
                    }
                }

                double totalWidth = gradientWidth + roundAmount;

                GridLength edgeLength = new GridLength((double)totalWidth, GridUnitType.Pixel);
                GridLength gridCenterHeight;
                GridLength gridCenterWidth;

                if (this.GlowDirection == GlowDirection.Inner)
                {
                    if ((2.0 * gradientWidth) > content.Height)
                    {
                        gradientWidth = Math.Round(content.Height / 2.0);
                    }

                    if ((2.0 * gradientWidth) > content.Width)
                    {
                        gradientWidth = Math.Round(content.Width / 2.0);
                    }

                    edgeLength = new GridLength((double)(gradientWidth > roundAmount ? gradientWidth : roundAmount), GridUnitType.Pixel);

                    this.CreateGradients(gradientWidth, roundAmount);

                    gridCenterHeight = new GridLength(1, GridUnitType.Star);
                    gridCenterWidth = new GridLength(1, GridUnitType.Star);
                    
                    this._layoutPart.Width = content.Width;
                    this._layoutPart.Height = content.Height;

                    RectangleGeometry rectangle = new RectangleGeometry();
                    rectangle.RadiusX = roundAmount;
                    rectangle.RadiusY = roundAmount;
                    rectangle.Rect = new Rect(0, 0, this._layoutPart.Width, this._layoutPart.Height);
                    this._layoutPart.Clip = rectangle;

                    TranslateTransform t = new TranslateTransform();
                    t.X = 0;
                    t.Y = 0;
                    TransformGroup transformGroup = new TransformGroup();
                    transformGroup.Children.Add(t);
                    this._layoutPart.RenderTransform = transformGroup;
                }
                else
                {
                    this.CreateGradients(gradientWidth, roundAmount);

                    gridCenterHeight = new GridLength(this._gradientBaseHeight - (2.0 * roundAmount), GridUnitType.Pixel);
                    gridCenterWidth = new GridLength(this._gradientBaseWidth - (2.0 * roundAmount), GridUnitType.Pixel);
                    this._layoutPart.Width = this._gradientBaseWidth + (2.0 * totalWidth);
                    this._layoutPart.Height = this._gradientBaseHeight + (2.0 * totalWidth);

                    TranslateTransform translateTransform = new TranslateTransform();
                    translateTransform.X = Math.Round(-gradientWidth);
                    translateTransform.Y = Math.Round(-gradientWidth);
                    TransformGroup transformGroup = new TransformGroup();
                    transformGroup.Children.Add(translateTransform);
                    this._layoutPart.RenderTransform = transformGroup;
                }

                this._layoutPart.ColumnDefinitions[1].Width = gridCenterWidth;
                this._layoutPart.RowDefinitions[1].Height = gridCenterHeight;
                this._layoutPart.ColumnDefinitions[0].Width = edgeLength;
                this._layoutPart.ColumnDefinitions[2].Width = edgeLength;
                this._layoutPart.RowDefinitions[0].Height = edgeLength;
                this._layoutPart.RowDefinitions[2].Height = edgeLength;
            }
        }

        private void CreateGradients(double width, double roundAmount)
        {
            Color startColor = Color.FromArgb(0x00, this.GlowColor.R, this.GlowColor.G, this.GlowColor.B);
            Color endColor;

            if (this.GlowOpactiy < 1.0)
            {
                endColor = Color.FromArgb(this.GlowColor.A, this.GlowColor.R, this.GlowColor.G, this.GlowColor.B);
                endColor.A = (byte)(255 * this.GlowOpactiy);
            }
            else
            {
                endColor = Color.FromArgb(this.GlowColor.A, this.GlowColor.R, this.GlowColor.G, this.GlowColor.B);
            }

            if (this.GlowDirection == GlowDirection.Inner)
            {
                endColor = Color.FromArgb(0x0, this.GlowColor.R, this.GlowColor.G, this.GlowColor.B);

                if (this.GlowOpactiy < 1.0)
                {
                    startColor = Color.FromArgb(this.GlowColor.A, this.GlowColor.R, this.GlowColor.G, this.GlowColor.B);
                    startColor.A = (byte)(255 * this.GlowOpactiy);
                }
                else
                {
                    startColor = Color.FromArgb(this.GlowColor.A, this.GlowColor.R, this.GlowColor.G, this.GlowColor.B);
                }
            }

            this.DrawTopLeftGradient(startColor, endColor);
            this.DrawTopGradient(startColor, endColor);
            this.DrawTopRightGradient(startColor, endColor);
            this.DrawMiddleRightGradient(startColor, endColor);
            this.DrawBottomRightGradient(startColor, endColor);
            this.DrawBottomGradient(startColor, endColor);
            this.DrawBottomLeftGradient(startColor, endColor);
            this.DrawMiddleLeftGradient(startColor, endColor);
            this.DrawMiddle(endColor);
        }

        private void DrawBottomRightGradient(Color startColor, Color endColor)
        {
            RadialGradientBrush radialGradientBrush = new RadialGradientBrush();
            TransformGroup transformGroup = new TransformGroup();

            double roundingOffset = (this._adjustedGradientWidth > 0) ? this._adjustedCornerRadius.BottomRight / (this._adjustedGradientWidth + this._adjustedCornerRadius.BottomRight) : 0.999;

            GradientStop gradientStop = new GradientStop();
            gradientStop.Color = startColor;
            gradientStop.Offset = 1.0;

            radialGradientBrush.GradientStops.Add(gradientStop);

            gradientStop = new GradientStop();
            gradientStop.Color = endColor;
            gradientStop.Offset = roundingOffset;

            radialGradientBrush.GradientStops.Add(gradientStop);

            ScaleTransform scaleTransform = new ScaleTransform();
            scaleTransform.CenterX = 0.5;
            scaleTransform.CenterY = 0.5;
            scaleTransform.ScaleX = 2;
            scaleTransform.ScaleY = 2;

            transformGroup.Children.Add(scaleTransform);

            SkewTransform skewTransform = new SkewTransform();
            skewTransform.CenterX = 0.5;
            skewTransform.CenterY = 0.5;

            transformGroup.Children.Add(skewTransform);

            RotateTransform rotateTransform = new RotateTransform();
            rotateTransform.CenterX = 0.5;
            rotateTransform.CenterY = 0.5;

            transformGroup.Children.Add(rotateTransform);

            TranslateTransform translateTransform = new TranslateTransform();
            translateTransform.X = -0.5;
            translateTransform.Y = -0.5;

            transformGroup.Children.Add(translateTransform);

            radialGradientBrush.RelativeTransform = transformGroup;

            this._rectangleBottomRightPart.Fill = radialGradientBrush;
            this._rectangleBottomRightPart.StrokeThickness = 0;
        }

        private void DrawBottomGradient(Color startColor, Color endColor)
        {
            LinearGradientBrush linearGradientBrush = new LinearGradientBrush();

            double roundingOffset = (this._adjustedGradientWidth > 0) ? this._adjustedCornerRadius.BottomLeft / (this._adjustedGradientWidth + this._adjustedCornerRadius.BottomLeft) : 0.999;

            linearGradientBrush.StartPoint = new Point(0.5, 0.0);
            linearGradientBrush.EndPoint = new Point(0.5, 1.0);

            GradientStop gradientStop = new GradientStop();
            gradientStop.Color = startColor;
            gradientStop.Offset = 1.0;

            linearGradientBrush.GradientStops.Add(gradientStop);

            gradientStop = new GradientStop();
            gradientStop.Color = endColor;
            gradientStop.Offset = roundingOffset;

            linearGradientBrush.GradientStops.Add(gradientStop);

            this._rectangleBottomPart.Fill = linearGradientBrush;
        }

        private void DrawBottomLeftGradient(Color startColor, Color endColor)
        {
            RadialGradientBrush radialGradientBrush = new RadialGradientBrush();
            TransformGroup transformGroup = new TransformGroup();

            double roundingOffset = (this._adjustedGradientWidth > 0) ? this._adjustedCornerRadius.BottomLeft / (this._adjustedGradientWidth + this._adjustedCornerRadius.BottomLeft) : 0.999;

            GradientStop gradientStop = new GradientStop();
            gradientStop.Color = startColor;
            gradientStop.Offset = 1.0;

            radialGradientBrush.GradientStops.Add(gradientStop);

            gradientStop = new GradientStop();
            gradientStop.Color = endColor;
            gradientStop.Offset = roundingOffset;

            radialGradientBrush.GradientStops.Add(gradientStop);

            ScaleTransform scaleTransform = new ScaleTransform();
            scaleTransform.CenterX = 0.5;
            scaleTransform.CenterY = 0.5;
            scaleTransform.ScaleX = 2;
            scaleTransform.ScaleY = 2;

            transformGroup.Children.Add(scaleTransform);

            SkewTransform skewTransform = new SkewTransform();
            skewTransform.CenterX = 0.5;
            skewTransform.CenterY = 0.5;
            
            transformGroup.Children.Add(skewTransform);

            RotateTransform rotateTransform = new RotateTransform();
            rotateTransform.CenterX = 0.5;
            rotateTransform.CenterY = 0.5;

            transformGroup.Children.Add(rotateTransform);

            TranslateTransform translateTransform = new TranslateTransform();
            translateTransform.X = 0.5;
            translateTransform.Y = -0.5;

            transformGroup.Children.Add(translateTransform);

            radialGradientBrush.RelativeTransform = transformGroup;

            this._rectangleBottomLeftPart.Fill = radialGradientBrush;
            this._rectangleBottomLeftPart.StrokeThickness = 0;
        }

        private void DrawMiddleRightGradient(Color startColor, Color endColor)
        {
            LinearGradientBrush linearGradientBrush = new LinearGradientBrush();

            double roundingOffset = (this._adjustedGradientWidth > 0) ? this._adjustedCornerRadius.TopRight / (this._adjustedGradientWidth + this._adjustedCornerRadius.TopRight) : 0.999;

            linearGradientBrush.StartPoint = new Point(1.0, 0.5);
            linearGradientBrush.EndPoint = new Point(0.0, 0.5);

            GradientStop gradientStop = new GradientStop();
            gradientStop.Color = startColor;
            gradientStop.Offset = 0.0;

            linearGradientBrush.GradientStops.Add(gradientStop);

            gradientStop = new GradientStop();
            gradientStop.Color = endColor;
            gradientStop.Offset = 1.0 - roundingOffset;

            linearGradientBrush.GradientStops.Add(gradientStop);

            this._rectangleMiddleRightPart.Fill = linearGradientBrush;
        }

        private void DrawMiddleLeftGradient(Color startColor, Color endColor)
        {
            LinearGradientBrush linearGradientBrush = new LinearGradientBrush();

            double roundingOffset = (this._adjustedGradientWidth > 0) ? this._adjustedCornerRadius.TopLeft / (this._adjustedGradientWidth + this._adjustedCornerRadius.TopLeft) : 0.999;

            linearGradientBrush.StartPoint = new Point(1.0, 0.5);
            linearGradientBrush.EndPoint = new Point(0.0, 0.5);

            GradientStop gradientStop = new GradientStop();
            gradientStop.Color = startColor;
            gradientStop.Offset = 1.0;

            linearGradientBrush.GradientStops.Add(gradientStop);

            gradientStop = new GradientStop();
            gradientStop.Color = endColor;
            gradientStop.Offset = roundingOffset;

            linearGradientBrush.GradientStops.Add(gradientStop);

            this._rectangleMiddleLeftPart.Fill = linearGradientBrush;
        }

        private void DrawTopRightGradient(Color startColor, Color endColor)
        {
            RadialGradientBrush radialGradientBrush = new RadialGradientBrush();
            TransformGroup transformGroup = new TransformGroup();

            double roundingOffset = (this._adjustedGradientWidth > 0) ? this._adjustedCornerRadius.TopRight / (this._adjustedGradientWidth + this._adjustedCornerRadius.TopRight) : 0.999;

            GradientStop gradientStop = new GradientStop();
            gradientStop.Color = startColor;
            gradientStop.Offset = 1.0;

            radialGradientBrush.GradientStops.Add(gradientStop);

            gradientStop = new GradientStop();
            gradientStop.Color = endColor;
            gradientStop.Offset = roundingOffset;

            radialGradientBrush.GradientStops.Add(gradientStop);

            ScaleTransform scaleTransform = new ScaleTransform();
            scaleTransform.CenterX = 0.5;
            scaleTransform.CenterY = 0.5;
            scaleTransform.ScaleX = 2;
            scaleTransform.ScaleY = 2;

            transformGroup.Children.Add(scaleTransform);

            SkewTransform skewTransform = new SkewTransform();
            skewTransform.CenterX = 0.5;
            skewTransform.CenterY = 0.5;

            transformGroup.Children.Add(skewTransform);

            RotateTransform rotateTransform = new RotateTransform();
            rotateTransform.CenterX = 0.5;
            rotateTransform.CenterY = 0.5;

            transformGroup.Children.Add(rotateTransform);

            TranslateTransform translateTransform = new TranslateTransform();
            translateTransform.X = -0.5;
            translateTransform.Y = 0.5;

            transformGroup.Children.Add(translateTransform);

            radialGradientBrush.RelativeTransform = transformGroup;

            this._rectangleTopRightPart.Fill = radialGradientBrush;
            this._rectangleTopRightPart.StrokeThickness = 0;
        }

        private void DrawTopGradient(Color startColor, Color endColor)
        {
            LinearGradientBrush linearGradientBrush = new LinearGradientBrush();

            double roundingOffset = (this._adjustedGradientWidth > 0) ? this._adjustedCornerRadius.TopLeft / (this._adjustedGradientWidth + this._adjustedCornerRadius.TopLeft) : 0.999;

            linearGradientBrush.StartPoint = new Point(0.5, 0.0);
            linearGradientBrush.EndPoint = new Point(0.5, 1.0);

            GradientStop gradientStop = new GradientStop();
            gradientStop.Color = startColor;
            gradientStop.Offset = 0;
            linearGradientBrush.GradientStops.Add(gradientStop);
            gradientStop = new GradientStop();
            gradientStop.Color = endColor;
            gradientStop.Offset = 1.0 - roundingOffset;
            linearGradientBrush.GradientStops.Add(gradientStop);

            this._rectangleTopPart.Fill = linearGradientBrush;
        }

        private void DrawTopLeftGradient(Color startColor, Color endColor)
        {
            RadialGradientBrush radialGradientBrush = new RadialGradientBrush();
            TransformGroup transformGroup = new TransformGroup();

            double roundingOffset = (this._adjustedGradientWidth > 0) ? this._adjustedCornerRadius.TopLeft / (this._adjustedGradientWidth + this._adjustedCornerRadius.TopLeft) : 0.999;

            GradientStop gradientStop = new GradientStop();
            gradientStop.Color = startColor;
            gradientStop.Offset = 1.0;
            
            radialGradientBrush.GradientStops.Add(gradientStop);

            gradientStop = new GradientStop();
            gradientStop.Color = endColor;
            gradientStop.Offset = roundingOffset;
            
            radialGradientBrush.GradientStops.Add(gradientStop);

            ScaleTransform scaleTransform = new ScaleTransform();
            scaleTransform.CenterX = 0.5;
            scaleTransform.CenterY = 0.5;
            scaleTransform.ScaleX = 2;
            scaleTransform.ScaleY = 2;
            
            transformGroup.Children.Add(scaleTransform);

            SkewTransform skewTransform = new SkewTransform();
            skewTransform.CenterX = 0.5;
            skewTransform.CenterY = 0.5;
            
            transformGroup.Children.Add(skewTransform);

            RotateTransform rotateTransform = new RotateTransform();
            rotateTransform.CenterX = 0.5;
            rotateTransform.CenterY = 0.5;
            
            transformGroup.Children.Add(rotateTransform);

            TranslateTransform translateTransform = new TranslateTransform();
            translateTransform.X = 0.5;
            translateTransform.Y = 0.5;
            
            transformGroup.Children.Add(translateTransform);

            radialGradientBrush.RelativeTransform = transformGroup;

            this._rectangleTopLeftPart.Fill = radialGradientBrush;
            this._rectangleTopLeftPart.StrokeThickness = 0;
        }

        private void DrawMiddle(Color endColor)
        {
            SolidColorBrush s = new SolidColorBrush(endColor);
            this._rectangleMiddlePart.Fill = s;
        }
    }
}
